{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "\n",
    "api_key = os.getenv('MY_API_KEY')\n",
    "api_base = os.getenv('MY_API_BASE')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "llm两种应用范式\n",
    "* tooled-argumented\n",
    "工具增强，指的是大模型结合外部工具来完成复杂任务的能力；类似bingapi做天气搜索\n",
    "\n",
    "* agent\n",
    "是更上一层的抽象，只作为一个智能体，强调利用大模型作为推理引擎。自主规划，决定以一个什么样的顺序，使用某种工具来完成一个复杂的任务"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "提示词技术-ReACT框架\n",
    "https://www.promptingguide.ai/techniques/react"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "伪代码看agent结合tool怎么工作的\n",
    "```\n",
    "\n",
    "Agent{\n",
    "prompt = \"\"\"\n",
    "Answer the following questions as best you can. You have access to the following tools:\n",
    "{tool}\n",
    "....\n",
    "Use the following format:\n",
    "Question: the input question you must answer\n",
    "Thought: you should always think about what to do\n",
    "Action: the action to take, should be one of [{tool_names}]\n",
    "Action Input: the input to the action\n",
    "Observation: the result of the action\n",
    "... (this Thought/Action/Action Input/Observation can repeat N times)\n",
    "Thought: I now know the final answer\n",
    "Final Answer: the final answer to the original input question\"\"\"\n",
    "\"\"\"\n",
    "\n",
    "run(question){\n",
    "    tools = load_tools()\n",
    "    prompt.format('tool',tools)\n",
    "    add_system(prompt)\n",
    "    answer = \"\"\n",
    "    while(!answer.start_with(\"Final Answer\")){\n",
    "        answer = llm.predict()\n",
    "        if(answer.start_with(\"Action\")){\n",
    "            action,input = output_parser(answer)\n",
    "            real_action = get_action(action)\n",
    "            obs = real_action.do_action(input)\n",
    "            add_system(obs)\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n",
    "}\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "看看langchain中怎么使用的，在langchain中tool和agent通常是一起使用的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\n",
      "\n",
      "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mAnswer the following questions as best you can. You have access to the following tools:\n",
      "\n",
      "arxiv: A wrapper around Arxiv.org Useful for when you need to answer questions about Physics, Mathematics, Computer Science, Quantitative Biology, Quantitative Finance, Statistics, Electrical Engineering, and Economics from scientific articles on arxiv.org. Input should be a search query.\n",
      "\n",
      "Use the following format:\n",
      "\n",
      "Question: the input question you must answer\n",
      "Thought: you should always think about what to do\n",
      "Action: the action to take, should be one of [arxiv]\n",
      "Action Input: the input to the action\n",
      "Observation: the result of the action\n",
      "... (this Thought/Action/Action Input/Observation can repeat N times)\n",
      "Thought: I now know the final answer\n",
      "Final Answer: the final answer to the original input question\n",
      "\n",
      "Begin!\n",
      "\n",
      "Question: what's the paper 1605.08386 about?\n",
      "Thought:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mI should use the arxiv tool to search for the paper with the given identifier.\n",
      "Action: arxiv\n",
      "Action Input: \"1605.08386\"\u001b[0m\n",
      "Observation: \u001b[36;1m\u001b[1;3mPublished: 2016-05-26\n",
      "Title: Heat-bath random walks with Markov bases\n",
      "Authors: Caprice Stanley, Tobias Windisch\n",
      "Summary: Graphs on lattice points are studied whose edges come from a finite set of\n",
      "allowed moves of arbitrary length. We show that the diameter of these graphs on\n",
      "fibers of a fixed integer matrix can be bounded from above by a constant. We\n",
      "then study the mixing behaviour of heat-bath random walks on these graphs. We\n",
      "also state explicit conditions on the set of moves so that the heat-bath random\n",
      "walk, a generalization of the Glauber dynamics, is an expander in fixed\n",
      "dimension.\u001b[0m\n",
      "Thought:\n",
      "\n",
      "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mAnswer the following questions as best you can. You have access to the following tools:\n",
      "\n",
      "arxiv: A wrapper around Arxiv.org Useful for when you need to answer questions about Physics, Mathematics, Computer Science, Quantitative Biology, Quantitative Finance, Statistics, Electrical Engineering, and Economics from scientific articles on arxiv.org. Input should be a search query.\n",
      "\n",
      "Use the following format:\n",
      "\n",
      "Question: the input question you must answer\n",
      "Thought: you should always think about what to do\n",
      "Action: the action to take, should be one of [arxiv]\n",
      "Action Input: the input to the action\n",
      "Observation: the result of the action\n",
      "... (this Thought/Action/Action Input/Observation can repeat N times)\n",
      "Thought: I now know the final answer\n",
      "Final Answer: the final answer to the original input question\n",
      "\n",
      "Begin!\n",
      "\n",
      "Question: what's the paper 1605.08386 about?\n",
      "Thought:I should use the arxiv tool to search for the paper with the given identifier.\n",
      "Action: arxiv\n",
      "Action Input: \"1605.08386\"\n",
      "Observation: Published: 2016-05-26\n",
      "Title: Heat-bath random walks with Markov bases\n",
      "Authors: Caprice Stanley, Tobias Windisch\n",
      "Summary: Graphs on lattice points are studied whose edges come from a finite set of\n",
      "allowed moves of arbitrary length. We show that the diameter of these graphs on\n",
      "fibers of a fixed integer matrix can be bounded from above by a constant. We\n",
      "then study the mixing behaviour of heat-bath random walks on these graphs. We\n",
      "also state explicit conditions on the set of moves so that the heat-bath random\n",
      "walk, a generalization of the Glauber dynamics, is an expander in fixed\n",
      "dimension.\n",
      "Thought:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mI now know the final answer.\n",
      "Final Answer: The paper 1605.08386 is titled \"Heat-bath random walks with Markov bases\" and is authored by Caprice Stanley and Tobias Windisch. It discusses the study of graphs on lattice points and their mixing behavior with heat-bath random walks.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'The paper 1605.08386 is titled \"Heat-bath random walks with Markov bases\" and is authored by Caprice Stanley and Tobias Windisch. It discusses the study of graphs on lattice points and their mixing behavior with heat-bath random walks.'"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.agents import AgentType,load_tools,initialize_agent,AgentExecutor,ZeroShotAgent\n",
    "from langchain.chat_models import ChatOpenAI\n",
    "\n",
    "llm = ChatOpenAI(api_key=api_key,base_url=api_base)\n",
    "\n",
    "tools = load_tools([\"arxiv\"])\n",
    "\n",
    "agent = initialize_agent(tools,llm,agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,verbose=True)\n",
    "\n",
    "agent.run(\"what's the paper 1605.08386 about?\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "几个方面简单看一下代码实现原理\n",
    "* tool\n",
    "* Agent是怎么执行的\n",
    "* ZeroShotAgent 的 AgentOutputParser\n",
    "* 最核心的prompt，ZeroShotAgent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "开发一个demo，使用自定义tool，出行助手\n",
    "* 天气预报/langchain集成\n",
    "* 机票预定\n",
    "* 酒店预订"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "os.environ['openweathermap_api_key'] = \"6515bb3582e8427298c0c38d2ada0508\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "自定义tool：预定机票，预订酒店\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.tools import StructuredTool\n",
    "\n",
    "def book_flight(date: str) -> str:\n",
    "    \"\"\"userful for when you need to book a flight\"\"\"\n",
    "    return f\"book flight for {date} success\"\n",
    "\n",
    "def book_hotel(start_date: str , end_date: str, location: str) -> str:\n",
    "    \"\"\"userful for when you need to book a hotel\"\"\"\n",
    "    return f\"book hotel in {location} from {start_date} to {end_date} success\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\n",
      "\n",
      "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mSystem: Respond to the human as helpfully and accurately as possible. You have access to the following tools:\n",
      "\n",
      "OpenWeatherMap: A wrapper around OpenWeatherMap API. Useful for fetching current weather information for a specified location. Input should be a location string (e.g. London,GB)., args: {{'location': {{'title': 'Location', 'type': 'string'}}}}\n",
      "book_flight: book_flight(date: str) -> str - userful for when you need to book a flight, args: {{'date': {{'title': 'Date', 'type': 'string'}}}}\n",
      "book_hotel: book_hotel(start_date: str, end_date: str, location: str) -> str - userful for when you need to book a hotel, args: {{'start_date': {{'title': 'Start Date', 'type': 'string'}}, 'end_date': {{'title': 'End Date', 'type': 'string'}}, 'location': {{'title': 'Location', 'type': 'string'}}}}\n",
      "\n",
      "Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).\n",
      "\n",
      "Valid \"action\" values: \"Final Answer\" or OpenWeatherMap, book_flight, book_hotel\n",
      "\n",
      "Provide only ONE action per $JSON_BLOB, as shown:\n",
      "\n",
      "```\n",
      "{\n",
      "  \"action\": $TOOL_NAME,\n",
      "  \"action_input\": $INPUT\n",
      "}\n",
      "```\n",
      "\n",
      "Follow this format:\n",
      "\n",
      "Question: input question to answer\n",
      "Thought: consider previous and subsequent steps\n",
      "Action:\n",
      "```\n",
      "$JSON_BLOB\n",
      "```\n",
      "Observation: action result\n",
      "... (repeat Thought/Action/Observation N times)\n",
      "Thought: I know what to respond\n",
      "Action:\n",
      "```\n",
      "{\n",
      "  \"action\": \"Final Answer\",\n",
      "  \"action_input\": \"Final response to human\"\n",
      "}\n",
      "```\n",
      "\n",
      "Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. Respond directly if appropriate. Format is Action:```$JSON_BLOB```then Observation:.\n",
      "Thought:\n",
      "Human: 我2023-12-15到2023-12-20日要去成都游玩，帮我看看天气如何？然后定好酒店和机票。\n",
      "\n",
      "\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mThought: The user wants to know the weather in Chengdu from December 15th to December 20th, 2023. They also need assistance in booking a hotel and flight for those dates. I will first check the weather using the OpenWeatherMap tool, and then proceed to book the hotel and flight.\n",
      "\n",
      "Action:\n",
      "```json\n",
      "{\n",
      "  \"action\": \"OpenWeatherMap\",\n",
      "  \"action_input\": {\n",
      "    \"location\": \"Chengdu\"\n",
      "  }\n",
      "}\n",
      "```\u001b[0m\n",
      "Observation: \u001b[36;1m\u001b[1;3mIn Chengdu, the current weather is as follows:\n",
      "Detailed status: clear sky\n",
      "Wind speed: 3 m/s, direction: 340°\n",
      "Humidity: 71%\n",
      "Temperature: \n",
      "  - Current: 10.94°C\n",
      "  - High: 11.91°C\n",
      "  - Low: 10.94°C\n",
      "  - Feels like: 9.94°C\n",
      "Rain: {}\n",
      "Heat index: None\n",
      "Cloud cover: 0%\u001b[0m\n",
      "Thought:\n",
      "\n",
      "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mSystem: Respond to the human as helpfully and accurately as possible. You have access to the following tools:\n",
      "\n",
      "OpenWeatherMap: A wrapper around OpenWeatherMap API. Useful for fetching current weather information for a specified location. Input should be a location string (e.g. London,GB)., args: {{'location': {{'title': 'Location', 'type': 'string'}}}}\n",
      "book_flight: book_flight(date: str) -> str - userful for when you need to book a flight, args: {{'date': {{'title': 'Date', 'type': 'string'}}}}\n",
      "book_hotel: book_hotel(start_date: str, end_date: str, location: str) -> str - userful for when you need to book a hotel, args: {{'start_date': {{'title': 'Start Date', 'type': 'string'}}, 'end_date': {{'title': 'End Date', 'type': 'string'}}, 'location': {{'title': 'Location', 'type': 'string'}}}}\n",
      "\n",
      "Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).\n",
      "\n",
      "Valid \"action\" values: \"Final Answer\" or OpenWeatherMap, book_flight, book_hotel\n",
      "\n",
      "Provide only ONE action per $JSON_BLOB, as shown:\n",
      "\n",
      "```\n",
      "{\n",
      "  \"action\": $TOOL_NAME,\n",
      "  \"action_input\": $INPUT\n",
      "}\n",
      "```\n",
      "\n",
      "Follow this format:\n",
      "\n",
      "Question: input question to answer\n",
      "Thought: consider previous and subsequent steps\n",
      "Action:\n",
      "```\n",
      "$JSON_BLOB\n",
      "```\n",
      "Observation: action result\n",
      "... (repeat Thought/Action/Observation N times)\n",
      "Thought: I know what to respond\n",
      "Action:\n",
      "```\n",
      "{\n",
      "  \"action\": \"Final Answer\",\n",
      "  \"action_input\": \"Final response to human\"\n",
      "}\n",
      "```\n",
      "\n",
      "Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. Respond directly if appropriate. Format is Action:```$JSON_BLOB```then Observation:.\n",
      "Thought:\n",
      "Human: 我2023-12-15到2023-12-20日要去成都游玩，帮我看看天气如何？然后定好酒店和机票。\n",
      "\n",
      "This was your previous work (but I haven't seen any of it! I only see what you return as final answer):\n",
      "Thought: The user wants to know the weather in Chengdu from December 15th to December 20th, 2023. They also need assistance in booking a hotel and flight for those dates. I will first check the weather using the OpenWeatherMap tool, and then proceed to book the hotel and flight.\n",
      "\n",
      "Action:\n",
      "```json\n",
      "{\n",
      "  \"action\": \"OpenWeatherMap\",\n",
      "  \"action_input\": {\n",
      "    \"location\": \"Chengdu\"\n",
      "  }\n",
      "}\n",
      "```\n",
      "Observation: In Chengdu, the current weather is as follows:\n",
      "Detailed status: clear sky\n",
      "Wind speed: 3 m/s, direction: 340°\n",
      "Humidity: 71%\n",
      "Temperature: \n",
      "  - Current: 10.94°C\n",
      "  - High: 11.91°C\n",
      "  - Low: 10.94°C\n",
      "  - Feels like: 9.94°C\n",
      "Rain: {}\n",
      "Heat index: None\n",
      "Cloud cover: 0%\n",
      "Thought:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mThe weather in Chengdu from December 15th to December 20th, 2023 is currently clear with a temperature range of 10.94°C to 11.91°C. The wind speed is 3 m/s with a direction of 340° and the humidity is 71%. There is no rain expected during this period.\n",
      "\n",
      "Now, let's proceed with booking the hotel and flight.\n",
      "\n",
      "Action:\n",
      "```json\n",
      "{\n",
      "  \"action\": \"book_hotel\",\n",
      "  \"action_input\": {\n",
      "    \"start_date\": \"2023-12-15\",\n",
      "    \"end_date\": \"2023-12-20\",\n",
      "    \"location\": \"Chengdu\"\n",
      "  }\n",
      "}\n",
      "```\n",
      "\u001b[0m\n",
      "Observation: \u001b[38;5;200m\u001b[1;3mbook hotel in Chengdu from 2023-12-15 to 2023-12-20 success\u001b[0m\n",
      "Thought:\n",
      "\n",
      "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mSystem: Respond to the human as helpfully and accurately as possible. You have access to the following tools:\n",
      "\n",
      "OpenWeatherMap: A wrapper around OpenWeatherMap API. Useful for fetching current weather information for a specified location. Input should be a location string (e.g. London,GB)., args: {{'location': {{'title': 'Location', 'type': 'string'}}}}\n",
      "book_flight: book_flight(date: str) -> str - userful for when you need to book a flight, args: {{'date': {{'title': 'Date', 'type': 'string'}}}}\n",
      "book_hotel: book_hotel(start_date: str, end_date: str, location: str) -> str - userful for when you need to book a hotel, args: {{'start_date': {{'title': 'Start Date', 'type': 'string'}}, 'end_date': {{'title': 'End Date', 'type': 'string'}}, 'location': {{'title': 'Location', 'type': 'string'}}}}\n",
      "\n",
      "Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).\n",
      "\n",
      "Valid \"action\" values: \"Final Answer\" or OpenWeatherMap, book_flight, book_hotel\n",
      "\n",
      "Provide only ONE action per $JSON_BLOB, as shown:\n",
      "\n",
      "```\n",
      "{\n",
      "  \"action\": $TOOL_NAME,\n",
      "  \"action_input\": $INPUT\n",
      "}\n",
      "```\n",
      "\n",
      "Follow this format:\n",
      "\n",
      "Question: input question to answer\n",
      "Thought: consider previous and subsequent steps\n",
      "Action:\n",
      "```\n",
      "$JSON_BLOB\n",
      "```\n",
      "Observation: action result\n",
      "... (repeat Thought/Action/Observation N times)\n",
      "Thought: I know what to respond\n",
      "Action:\n",
      "```\n",
      "{\n",
      "  \"action\": \"Final Answer\",\n",
      "  \"action_input\": \"Final response to human\"\n",
      "}\n",
      "```\n",
      "\n",
      "Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. Respond directly if appropriate. Format is Action:```$JSON_BLOB```then Observation:.\n",
      "Thought:\n",
      "Human: 我2023-12-15到2023-12-20日要去成都游玩，帮我看看天气如何？然后定好酒店和机票。\n",
      "\n",
      "This was your previous work (but I haven't seen any of it! I only see what you return as final answer):\n",
      "Thought: The user wants to know the weather in Chengdu from December 15th to December 20th, 2023. They also need assistance in booking a hotel and flight for those dates. I will first check the weather using the OpenWeatherMap tool, and then proceed to book the hotel and flight.\n",
      "\n",
      "Action:\n",
      "```json\n",
      "{\n",
      "  \"action\": \"OpenWeatherMap\",\n",
      "  \"action_input\": {\n",
      "    \"location\": \"Chengdu\"\n",
      "  }\n",
      "}\n",
      "```\n",
      "Observation: In Chengdu, the current weather is as follows:\n",
      "Detailed status: clear sky\n",
      "Wind speed: 3 m/s, direction: 340°\n",
      "Humidity: 71%\n",
      "Temperature: \n",
      "  - Current: 10.94°C\n",
      "  - High: 11.91°C\n",
      "  - Low: 10.94°C\n",
      "  - Feels like: 9.94°C\n",
      "Rain: {}\n",
      "Heat index: None\n",
      "Cloud cover: 0%\n",
      "Thought:The weather in Chengdu from December 15th to December 20th, 2023 is currently clear with a temperature range of 10.94°C to 11.91°C. The wind speed is 3 m/s with a direction of 340° and the humidity is 71%. There is no rain expected during this period.\n",
      "\n",
      "Now, let's proceed with booking the hotel and flight.\n",
      "\n",
      "Action:\n",
      "```json\n",
      "{\n",
      "  \"action\": \"book_hotel\",\n",
      "  \"action_input\": {\n",
      "    \"start_date\": \"2023-12-15\",\n",
      "    \"end_date\": \"2023-12-20\",\n",
      "    \"location\": \"Chengdu\"\n",
      "  }\n",
      "}\n",
      "```\n",
      "\n",
      "Observation: book hotel in Chengdu from 2023-12-15 to 2023-12-20 success\n",
      "Thought:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mThe hotel in Chengdu has been successfully booked from December 15th to December 20th, 2023.\n",
      "\n",
      "Now, let's proceed with booking the flight.\n",
      "\n",
      "Action:\n",
      "```json\n",
      "{\n",
      "  \"action\": \"book_flight\",\n",
      "  \"action_input\": {\n",
      "    \"date\": \"2023-12-15\"\n",
      "  }\n",
      "}\n",
      "```\n",
      "\n",
      "\u001b[0m\n",
      "Observation: \u001b[33;1m\u001b[1;3mbook flight for 2023-12-15 success\u001b[0m\n",
      "Thought:\n",
      "\n",
      "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mSystem: Respond to the human as helpfully and accurately as possible. You have access to the following tools:\n",
      "\n",
      "OpenWeatherMap: A wrapper around OpenWeatherMap API. Useful for fetching current weather information for a specified location. Input should be a location string (e.g. London,GB)., args: {{'location': {{'title': 'Location', 'type': 'string'}}}}\n",
      "book_flight: book_flight(date: str) -> str - userful for when you need to book a flight, args: {{'date': {{'title': 'Date', 'type': 'string'}}}}\n",
      "book_hotel: book_hotel(start_date: str, end_date: str, location: str) -> str - userful for when you need to book a hotel, args: {{'start_date': {{'title': 'Start Date', 'type': 'string'}}, 'end_date': {{'title': 'End Date', 'type': 'string'}}, 'location': {{'title': 'Location', 'type': 'string'}}}}\n",
      "\n",
      "Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).\n",
      "\n",
      "Valid \"action\" values: \"Final Answer\" or OpenWeatherMap, book_flight, book_hotel\n",
      "\n",
      "Provide only ONE action per $JSON_BLOB, as shown:\n",
      "\n",
      "```\n",
      "{\n",
      "  \"action\": $TOOL_NAME,\n",
      "  \"action_input\": $INPUT\n",
      "}\n",
      "```\n",
      "\n",
      "Follow this format:\n",
      "\n",
      "Question: input question to answer\n",
      "Thought: consider previous and subsequent steps\n",
      "Action:\n",
      "```\n",
      "$JSON_BLOB\n",
      "```\n",
      "Observation: action result\n",
      "... (repeat Thought/Action/Observation N times)\n",
      "Thought: I know what to respond\n",
      "Action:\n",
      "```\n",
      "{\n",
      "  \"action\": \"Final Answer\",\n",
      "  \"action_input\": \"Final response to human\"\n",
      "}\n",
      "```\n",
      "\n",
      "Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. Respond directly if appropriate. Format is Action:```$JSON_BLOB```then Observation:.\n",
      "Thought:\n",
      "Human: 我2023-12-15到2023-12-20日要去成都游玩，帮我看看天气如何？然后定好酒店和机票。\n",
      "\n",
      "This was your previous work (but I haven't seen any of it! I only see what you return as final answer):\n",
      "Thought: The user wants to know the weather in Chengdu from December 15th to December 20th, 2023. They also need assistance in booking a hotel and flight for those dates. I will first check the weather using the OpenWeatherMap tool, and then proceed to book the hotel and flight.\n",
      "\n",
      "Action:\n",
      "```json\n",
      "{\n",
      "  \"action\": \"OpenWeatherMap\",\n",
      "  \"action_input\": {\n",
      "    \"location\": \"Chengdu\"\n",
      "  }\n",
      "}\n",
      "```\n",
      "Observation: In Chengdu, the current weather is as follows:\n",
      "Detailed status: clear sky\n",
      "Wind speed: 3 m/s, direction: 340°\n",
      "Humidity: 71%\n",
      "Temperature: \n",
      "  - Current: 10.94°C\n",
      "  - High: 11.91°C\n",
      "  - Low: 10.94°C\n",
      "  - Feels like: 9.94°C\n",
      "Rain: {}\n",
      "Heat index: None\n",
      "Cloud cover: 0%\n",
      "Thought:The weather in Chengdu from December 15th to December 20th, 2023 is currently clear with a temperature range of 10.94°C to 11.91°C. The wind speed is 3 m/s with a direction of 340° and the humidity is 71%. There is no rain expected during this period.\n",
      "\n",
      "Now, let's proceed with booking the hotel and flight.\n",
      "\n",
      "Action:\n",
      "```json\n",
      "{\n",
      "  \"action\": \"book_hotel\",\n",
      "  \"action_input\": {\n",
      "    \"start_date\": \"2023-12-15\",\n",
      "    \"end_date\": \"2023-12-20\",\n",
      "    \"location\": \"Chengdu\"\n",
      "  }\n",
      "}\n",
      "```\n",
      "\n",
      "Observation: book hotel in Chengdu from 2023-12-15 to 2023-12-20 success\n",
      "Thought:The hotel in Chengdu has been successfully booked from December 15th to December 20th, 2023.\n",
      "\n",
      "Now, let's proceed with booking the flight.\n",
      "\n",
      "Action:\n",
      "```json\n",
      "{\n",
      "  \"action\": \"book_flight\",\n",
      "  \"action_input\": {\n",
      "    \"date\": \"2023-12-15\"\n",
      "  }\n",
      "}\n",
      "```\n",
      "\n",
      "\n",
      "Observation: book flight for 2023-12-15 success\n",
      "Thought:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mThe flight for December 15th, 2023 has been successfully booked. \n",
      "\n",
      "Action:\n",
      "```json\n",
      "{\n",
      "  \"action\": \"Final Answer\",\n",
      "  \"action_input\": \"The weather in Chengdu from December 15th to December 20th, 2023 is expected to be clear with temperatures ranging from 10.94°C to 11.91°C. The wind speed will be 3 m/s with a direction of 340° and the humidity will be 71%. There is no rain expected during this period. The hotel in Chengdu has been booked from December 15th to December 20th, 2023 and the flight for December 15th, 2023 has also been booked.\"\n",
      "}\n",
      "```\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'The weather in Chengdu from December 15th to December 20th, 2023 is expected to be clear with temperatures ranging from 10.94°C to 11.91°C. The wind speed will be 3 m/s with a direction of 340° and the humidity will be 71%. There is no rain expected during this period. The hotel in Chengdu has been booked from December 15th to December 20th, 2023 and the flight for December 15th, 2023 has also been booked.'"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.agents import AgentType,load_tools,initialize_agent,AgentExecutor,StructuredChatAgent\n",
    "from langchain.chat_models import ChatOpenAI\n",
    "import langchain\n",
    "\n",
    "langchain.verbose = True\n",
    "llm = ChatOpenAI(api_key=api_key,base_url=api_base)\n",
    "\n",
    "tools = load_tools([\"openweathermap-api\"])\n",
    "tools = tools + [StructuredTool.from_function(book_flight),StructuredTool.from_function(book_hotel)]\n",
    "\n",
    "agent = initialize_agent(tools,llm,agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,verbose=True)\n",
    "\n",
    "agent.run(\"我2023-12-15到2023-12-20日要去成都游玩，帮我看看天气如何？然后定好酒店和机票。\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "然后从一些代码细节和提示词整个输入输出流程中，可以了解到langchain的tool和agent的原理是怎样的。\n",
    "基本上，langchain的agent就是使用了提示词技巧中的react框架，然后加上类似伪代码中的逻辑完成的。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "额外多开一起，讲讲现在最热门几个agent/tool开源项目。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
